using Godot;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using TopDownGodot.Src.Globals.Multiplayer;
using TopDownGodot.Src.Models.DTO;

namespace TopDownGodot.Src.Multiplayer
{
    public partial class CreateServer : Node
    {
        private PackedScene _characterChoices = GD.Load<PackedScene>("res://scene/character_choices.tscn");
        private LineEdit ServerNameField => GetNode<LineEdit>("GUI/Text/ServerName");
        private LineEdit PortField => GetNode<LineEdit>("GUI/Text/Port");
        private LineEdit PasswordField => GetNode<LineEdit>("GUI/Text/Password");

        private struct IpMask
        {
            public string IpStr { get; set; }
            public string MaskStr { get; set; }

            public IpMask(string ipStr, string maskStr) : this()
            {
                IpStr = ipStr;
                MaskStr = maskStr;
            }
        }

        private static List<IpMask> IpmaskList;

        public CreateServer()
        {
            IpmaskList ??= [];
            IpmaskList.Clear();
            // 这里包含127.0.0.1
            foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (netInterface.OperationalStatus == OperationalStatus.Up)
                {
                    foreach (UnicastIPAddressInformation ip in netInterface.GetIPProperties().UnicastAddresses)
                    {
                        if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            var ipStr = ip.Address.ToString();
                            var maskStr = ip.IPv4Mask.ToString();
                            IpmaskList.Add(new IpMask(ipStr, maskStr));
                        }
                    }
                }
            }
        }

        public void OnCreateButtonPressed()
        {
            ENetMultiplayerPeer peer = new();

            string roomName = ServerNameField.Text;
            int port = int.TryParse(PortField.Text, out var p) ? p : 0;
            string roomPassword = PasswordField.Text;
            int playerMaxNumber = 3;

            var peerInfo = peer.CreateServer(port, playerMaxNumber);
            if (peerInfo == Error.Ok)
            {
                GD.Print("Server create success");
                Multiplayer.MultiplayerPeer = peer;

                MultiplayerGlobal.RoomInfo ??= [];
                foreach (var item in IpmaskList)
                {
                    RoomInfoDTO roomInfoDTO = new()
                    {
                        Ip = item.IpStr,
                        Port = port,
                        Name = roomName,
                        MaxPlayers = playerMaxNumber + 1,
                        PlayersNumber = 1,
                        Mask = item.MaskStr
                    };

                    MultiplayerGlobal.RoomInfo.Add(roomInfoDTO);
                }

                GetTree().ChangeSceneToPacked(_characterChoices);
            }
            else
            {
                GD.Print($"Server creation failed，error info：{peerInfo}");
            }
        }

        private static string HashPassword(string password)
        {
            if (string.IsNullOrEmpty(password))
                return "";
            var ctx = new HashingContext();
            ctx.Start(HashingContext.HashType.Sha256);
            ctx.Update(password.ToUtf8Buffer());
            var sha256 = ctx.Finish(); // PackedByteArray  
            return sha256.HexEncode();
        }

        public void OnBackButtonPressed()
        {
            GetTree().ChangeSceneToFile("res://scene/multiplayer_scene.tscn");
        }
    }
}
